﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using Microsoft.Xna.Framework;
namespace DKE_Kinect.Entwicklung.PolyVox
{

    class VoxelStructComparer : IEqualityComparer<VoxelStruct>
    {
        public VoxelStructComparer() { }
        public bool Equals(VoxelStruct x, VoxelStruct y)
        {
            return (x.Position.Equals(y.Position));
        }

        public int GetHashCode(VoxelStruct x)
        {
            return (x.Position.GetHashCode());
        }
    }
    /// <summary>
    /// Klasse um Volumina zu speichern
    /// </summary>
    [Serializable()]
    public class PolyVoxRecord : ISerializable
    {
       private HashSet<VoxelStruct> pVoxelStruct;
    //   private List<VoxelStruct> pVoxelStruct;

       /// <summary>
       /// Initializes a new instance of the <see cref="PolyVoxRecord"/> class.
       /// </summary>
       public PolyVoxRecord()
       {
          pVoxelStruct = new HashSet<VoxelStruct>(new VoxelStructComparer());
      //     pVoxelStruct = new List<VoxelStruct>();
       }
       /// <summary>
       /// Initializes a new instance of the <see cref="PolyVoxRecord"/> class.
       /// </summary>
       /// <param name="info">The info.</param>
       /// <param name="context">The context.</param>
       public PolyVoxRecord(SerializationInfo info, StreamingContext context)
       {
           pVoxelStruct = new HashSet<VoxelStruct>(new VoxelStructComparer());
        //   pVoxelStruct = new List<VoxelStruct>();
           int count = (int)info.GetValue("count", typeof(int));
           for (int i = 0; i < count; ++i)
           {
              
               VoxelStruct v = (VoxelStruct)info.GetValue("v" + i, typeof(VoxelStruct));
               Voxel.SetColor(v.Color);
               Voxel.SetDensity(v.Density);
               if (v.Action == VoxelAction.set)
               {
                   Voxel.SetColor(v.Color);
                   Voxel.SetDensity(v.Density);
                   Application.PolyvoxManager.SetVoxelAt(v.Position);
                   pVoxelStruct.Remove(v);
                   pVoxelStruct.Add(v);
               }
               if (v.Action == VoxelAction.sphere)
               {
                   Voxel.SetColor(v.Color);
                   Voxel.SetDensity(v.Density);
                   Application.PolyvoxManager.SetSphereAt(v.Position, v.Radius);
                   pVoxelStruct.Remove(v);
                   pVoxelStruct.Add(v);
               }
               if (v.Action == VoxelAction.line)
               {
                   ++i;
                 
                       Voxel.SetColor(v.Color);
                       Voxel.SetDensity(v.Density);
                       VoxelStruct v2 = (VoxelStruct)info.GetValue("v" + i, typeof(VoxelStruct));
                       Application.PolyvoxManager.DrawLine(v.Position, v2.Position);
                       pVoxelStruct.Remove(v);
                       pVoxelStruct.Remove(v2);
                       pVoxelStruct.Add(v);
                       pVoxelStruct.Add(v2);
                   
               }
               if (v.Action == VoxelAction.block)
               {
                   ++i;

                   Voxel.SetColor(v.Color);
                   Voxel.SetDensity(v.Density);
                   VoxelStruct v2 = (VoxelStruct)info.GetValue("v" + i, typeof(VoxelStruct));
                   Application.PolyvoxManager.SetBlockAt(v.Position, v2.Position);
                   pVoxelStruct.Remove(v);
                   pVoxelStruct.Remove(v2);
                   pVoxelStruct.Add(v);
                   pVoxelStruct.Add(v2);
               }
            
           
           }
       }

       /// <summary>
       /// Sets the voxel.
       /// </summary>
       /// <param name="pos">The pos.</param>
       /// <param name="voxel">The voxel.</param>
       /// <param name="action">The action.</param>
       public void setVoxel(Vector3 pos, PolyVoxCore.MaterialDensityPair62 voxel,VoxelAction action)
       {
          VoxelStruct v= new VoxelStruct(pos, voxel,action);
        
              pVoxelStruct.Remove(v);
    
           pVoxelStruct.Add(v);
       }
       /// <summary>
       /// Sets the voxel.
       /// </summary>
       /// <param name="pos">The pos.</param>
       /// <param name="voxel">The voxel.</param>
       /// <param name="radius">The radius.</param>
       /// <param name="action">The action.</param>
       public void setVoxel(Vector3 pos, PolyVoxCore.MaterialDensityPair62 voxel, int radius,VoxelAction action)
       {
           VoxelStruct v = new VoxelStruct(pos, voxel,radius,action);

           pVoxelStruct.Remove(v);

           pVoxelStruct.Add(v);
       }



       #region ISerializable Member

       /// <summary>
       /// Füllt eine <see cref="T:System.Runtime.Serialization.SerializationInfo"/> mit den Daten, die zum Serialisieren des Zielobjekts erforderlich sind.
       /// </summary>
       /// <param name="info">Die mit Daten zu füllende <see cref="T:System.Runtime.Serialization.SerializationInfo"/>.</param>
       /// <param name="context">Das Ziel (siehe <see cref="T:System.Runtime.Serialization.StreamingContext"/>) dieser Serialisierung.</param>
       /// <exception cref="T:System.Security.SecurityException">Der Aufrufer verfügt nicht über die erforderliche Berechtigung. </exception>
       public void GetObjectData(SerializationInfo info, StreamingContext context)
       {
          
           VoxelStruct[] allVoxels = this.pVoxelStruct.ToArray();
           info.AddValue("count", allVoxels.Length);
           int i = 0;
           foreach (VoxelStruct v in allVoxels)
           {
               info.AddValue("v" + i, v);
               i += 1;
           }
           if (allVoxels.Length != 0)
           {
               VoxelStruct vox = allVoxels[allVoxels.Length - 1];
               info.AddValue("v" + i, new VoxelStruct(vox.Position, new PolyVoxCore.MaterialDensityPair62(vox.Color, vox.Density), VoxelAction.set));
           }
       }

      

       #endregion
    }
}
